package cn.itcast.protocol;

import cn.itcast.config.Config;
import cn.itcast.message.Message;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageCodec;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;

/**
 * @Author: LDeng
 * @Date: 2021-06-03 20:05
 */

@ChannelHandler.Sharable
@Slf4j
//必须和LengthFieldBasedFrameDecoder一起使用，确保接到的Bytebuf消息是完整的
public class MessageCodecSharable extends MessageToMessageCodec<ByteBuf,Message> {
    @Override
    protected void encode(ChannelHandlerContext ctx, Message msg, List<Object> outList) throws Exception {
        ByteBuf out=ctx.alloc().buffer();
        //1，4个字节-魔数
        out.writeBytes(new byte[]{1, 2, 3, 4});
        //2，一个字节 -版本
        out.writeByte(1);
        //3, 一个字节 -序列化算法 /0，jdk/1,json
        out.writeByte(Config.getSerializerAlgorithm().ordinal());
        //4, 一个字节 - 指令类型 - 登录/注册/群聊/单聊。。。业务相关, 来自子类实现父类的抽象方法getMessageType()
        out.writeByte(msg.getMessageType());
        //5, 4字节请求序号
        out.writeInt(msg.getSequenceId());
        out.writeByte(0xff);//无意义， 填充凑齐16字节
        //6, 对象（msg）->字节数组
        byte[] bytes = Config.getSerializerAlgorithm().serialize(msg);
        //7, 正文长度
        out.writeInt(bytes.length);
        //8, 获取内容字节数组
        out.writeBytes(bytes);
        outList.add(out);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        int magicNumber = in.readInt();
        byte version = in.readByte();
        byte serializerAlgorithm = in.readByte();
        byte messageType = in.readByte();
        int sequenceId = in.readInt();
        in.readByte();
        int length = in.readInt();
        //读取正文字节数组并转对象
        byte[] bytes = new byte[length];
        in.readBytes(bytes, 0, length);
        //从字节数组中获取序列化算法
        Serializer.Algorithm algorithm = Serializer.Algorithm.values()[serializerAlgorithm];
        //从字节数组中获取确定具体消息类型
        Class<?> messageClass = Message.getMessageClass(messageType);
        Object deserialize = algorithm.deserialize(messageClass, bytes);
//        log.debug("magicNumber->{},version->{},serializerType->{}," +
//                "messageType->{},sequenceId->{},length->{}",magicNumber,version,serializerType, messageType,sequenceId,length);
//        log.debug("message对象->{}",message);

        //传递给下个handler用
        out.add(deserialize);
    }
}
